package com.arpa.oms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.arpa.core.web.Result;
import com.arpa.ntocc.common.common.cache.PartyCache;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.oms.domain.dto.OmsSaleReturnDTO;
import com.arpa.oms.domain.dto.OmsSaleReturnItemDTO;
import com.arpa.oms.domain.entity.*;
import com.arpa.oms.domain.enums.OmsGoodTypeEnum;
import com.arpa.oms.domain.enums.OrderStatusEnum;
import com.arpa.oms.domain.vo.OmsSaleReturnItemVO;
import com.arpa.oms.domain.vo.OmsSaleReturnVO;
import com.arpa.oms.mapper.OmsSaleReturnMapper;
import com.arpa.oms.service.*;
import com.arpa.wms.cache.CustomerCache;
import com.arpa.wms.cache.GoodsCache;
import com.arpa.wms.cache.WarehouseCache;
import com.arpa.wms.common.util.OrderIdGeneratorUtil;
import com.arpa.wms.domain.consts.NumConst;
import com.arpa.wms.domain.entity.Goods;
import com.arpa.wms.domain.entity.Putaway;
import com.arpa.wms.domain.enums.ReceiveTypeEnum;
import com.arpa.wms.service.IReceiveService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.arpa.wms.domain.consts.NumConst.NUM_ZERO;

/**
 * <p>
 * OMS销售退货单 服务实现类
 * </p>
 *
 * @author LEO
 * @since 2020-11-17
 */
@Service
public class OmsSaleReturnServiceImpl extends ServiceImpl<OmsSaleReturnMapper, OmsSaleReturn> implements IOmsSaleReturnService {

    @Autowired
    private PartyCache partyCache;

    @Autowired
    private WarehouseCache warehouseCache;

    @Autowired
    private ISaleService iSaleService;

    @Autowired
    private ISaleItemService iSaleItemService;

    @Autowired
    private IOmsSaleReturnItemService iSaleReturnItemService;

    @Autowired
    private GoodsCache goodsCache;

    @Autowired
    private IOmsOutboundService iOmsOutboundService;

    @Autowired
    private IReceiveService iReceiveService;

    @Autowired
    private CustomerCache customerCache;
    @Autowired
    private IOmsGoodsRelationItemService iOmsGoodsRelationItemService;

    // XYTODO TODO 计算百分数，除以100时计算的常量    后期可统一放到公用文件中
    public static final BigDecimal DECIMAL100 = new BigDecimal("100");

    /**
     * 保存
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean save(OmsSaleReturn entity) {
        if (StringUtils.isBlank(entity.getCreatedBy())) {
            entity.setCreatedBy(UserUtil.getCode());
            entity.setCreatedName(partyCache.translate(UserUtil.getCode()));
            entity.setModifiedBy(UserUtil.getCode());
            entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
        }
        return super.save(entity);
    }

    /**
     * 根据code更新实体
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public int updateByCode(OmsSaleReturn entity) {
        if (StringUtils.isBlank(entity.getModifiedBy())) {
            entity.setModifiedBy(UserUtil.getCode());
            entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
        }
        return baseMapper.update(entity, new QueryWrapper<OmsSaleReturn>().lambda().eq(OmsSaleReturn::getCode, entity.getCode()).eq(OmsSaleReturn::getGroupCode,UserUtil.getBranchCode()));
    }

    /**
     * 查询列表
     *
     * @param omsSaleReturnDTO
     * @return
     */
    @Override
    public List<OmsSaleReturnVO> queryList(OmsSaleReturnDTO omsSaleReturnDTO) {
        //排序字段名需要驼峰转数据库下划线类型字段名
        if (StringUtils.isNotEmpty(omsSaleReturnDTO.getSortField())) {
            omsSaleReturnDTO.setSortField(CommonUtil.camel2Underline(omsSaleReturnDTO.getSortField()));
        }
        List<OmsSaleReturnVO> omsSaleReturnVOList = baseMapper.queryList(omsSaleReturnDTO);
        // 翻译
        omsSaleReturnVOList.forEach(e -> {
            //e.setWarehouseName(warehouseCache.translate(e.getWarehouseCode()));
            e.setTypeText(ReceiveTypeEnum.translate(e.getType()));
            e.setStatusText(OrderStatusEnum.translate(e.getStatus()));
        });


        return omsSaleReturnVOList;
    }

    /**
     * 查询合计,包含总数
     *
     * @param omsSaleReturnDTO
     * @return
     */
    @Override
    public OmsSaleReturnVO queryListSum(OmsSaleReturnDTO omsSaleReturnDTO) {
        OmsSaleReturnVO omsSaleReturnVO = baseMapper.queryListSum(omsSaleReturnDTO);
        return omsSaleReturnVO;
    }

    /**
     * 作废
     *
     * @param code
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Result annul(String code) {
        // 判断状态
        OmsSaleReturn dbEntity = this.getOne(new QueryWrapper<OmsSaleReturn>().lambda().eq(OmsSaleReturn::getCode, code));
        if (ObjectUtil.isNull(dbEntity)) {
            throw new ServiceException("单据不存在");
        }
        if (!(ObjectUtil.equal(OrderStatusEnum.NEWS.getValue(), dbEntity.getStatus())
                || ObjectUtil.equal(OrderStatusEnum.NO_PASS.getValue(), dbEntity.getStatus()))) {
            throw new ServiceException("非新增或审核不通过状态单据，无法作废");
        }
        // 修改状态
        this.update(new UpdateWrapper<OmsSaleReturn>().lambda().eq(OmsSaleReturn::getCode, code)
                .set(OmsSaleReturn::getModifiedBy, UserUtil.getCode())
                .set(OmsSaleReturn::getModifiedName, partyCache.translate(UserUtil.getCode()))
                .set(OmsSaleReturn::getStatus, OrderStatusEnum.ANNUL.getValue()));
        return Result.ok();
    }

    /**
     * 保存/修改
     *
     * @param entity
     * @return
     */
    @Override
    public Result localSave(OmsSaleReturn entity) {
        // 插入标记，如果是新增，则true，修改则为false
        boolean insertFlag = true;

        if (IterUtil.isEmpty(entity.getSaleReturnItemList())) {
            throw new ServiceException("退货明细不能为空");
        }
        // 校验销售订单信息
        if (StrUtil.isBlank(entity.getSourceCode())) {
            throw new ServiceException("销售订单号不能为空");
        }
        Sale sale = iSaleService.getOne(new QueryWrapper<Sale>().lambda().eq(Sale::getCode, entity.getSourceCode()));
        if (ObjectUtil.isNull(sale)) {
            throw new ServiceException("销售订单【" + entity.getSourceCode() + "】不存在");
        }

        // 判断code，如果有值，则是更新，则判断状态，如果没值，则不用判断
        if (StrUtil.isNotBlank(entity.getCode())) {
            // 更新时，判断单据正确性、状态正确性
            OmsSaleReturn dbEntity = this.getOne(new QueryWrapper<OmsSaleReturn>().lambda().eq(OmsSaleReturn::getCode, entity.getCode()));
            if (ObjectUtil.isNull(dbEntity)) {
                throw new ServiceException("单据【" + entity.getCode() + "】不存在");
            }
            if (!(ObjectUtil.equal(entity.getStatus(), OrderStatusEnum.NEWS.getValue())
                    || ObjectUtil.equal(entity.getStatus(), OrderStatusEnum.NO_PASS.getValue()))) {
                throw new ServiceException("单据状态不正确，无法保存");
            }
            insertFlag = false;
        }

        // 重新计算一遍数据
        calcQuantity(entity, true);

        // 校验数量是否超过可退数量
        localSaveValidRefundQuantity(entity.getSaleReturnItemList());

        entity.setType(ReceiveTypeEnum.SALE_RETURN.getValue());
        entity.setCustomerName(customerCache.translate(entity.getCustomerCode()));
        entity.setShipmentCode(UserUtil.getShipmentCompanyCode());
        entity.setShipmentName(UserUtil.getShipmentCompanyName());
        entity.setGroupCode(UserUtil.getBranchCode());

        // 判断flag，保存或update 主单
        if (insertFlag) {
            entity.setCode(OrderIdGeneratorUtil.generatorOmsOrderId(OrderIdGeneratorUtil.OrderTypeEnum.ST, entity.getShipmentCode(),UserUtil.getBranchCode()));
            entity.setStatus(OrderStatusEnum.NEWS.getValue());
            save(entity);
        } else {
            entity.setModifiedBy(UserUtil.getCode());
            entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
            this.update(entity, new QueryWrapper<OmsSaleReturn>().lambda().eq(OmsSaleReturn::getCode, entity.getCode()));
        }

        // 删除数据库中的子单
        iSaleReturnItemService.remove(new QueryWrapper<OmsSaleReturnItem>().lambda().eq(OmsSaleReturnItem::getSaleReturnCode, entity.getCode()));

        // 子单添加信息
        entity.getSaleReturnItemList().forEach(r -> {
            r.setCode(IdUtil.simpleUUID());
            r.setSaleReturnCode(entity.getCode());
            r.setCreatedBy(entity.getCreatedBy());
            r.setCreatedName(entity.getCreatedName());
            r.setModifiedBy(entity.getModifiedBy());
            r.setModifiedName(entity.getModifiedName());
        });
        // 保存子单
        iSaleReturnItemService.saveBatch(entity.getSaleReturnItemList());

        return Result.ok();
    }

    /**
     * @param entity :
     * @description 提交 销售退货单
     * @author xuyang
     * @date 2020/12/14 13:43
     **/
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void submit(OmsSaleReturn entity) {
        // 插入标记，如果是新增，则true，修改则为false
        boolean insertFlag = true;

        if (IterUtil.isEmpty(entity.getSaleReturnItemList())) {
            throw new ServiceException("退货明细不能为空");
        }
        // 校验销售订单信息
        if (StrUtil.isBlank(entity.getSourceCode())) {
            throw new ServiceException("销售订单号不能为空");
        }
        Sale sale = iSaleService.getOne(new QueryWrapper<Sale>().lambda().eq(Sale::getCode, entity.getSourceCode()));
        if (ObjectUtil.isNull(sale)) {
            throw new ServiceException("销售订单【" + entity.getSourceCode() + "】不存在");
        }

        // 判断code，如果有值，则是更新,需要判断状态，如果没值，则不用判断
        if (StrUtil.isNotBlank(entity.getCode())) {
            // 更新时，判断单据正确性、状态正确性
            OmsSaleReturn dbEntity = this.getOne(new QueryWrapper<OmsSaleReturn>().lambda().eq(OmsSaleReturn::getCode, entity.getCode()));
            if (ObjectUtil.isNull(dbEntity)) {
                throw new ServiceException("单据【" + entity.getCode() + "】不存在");
            }
            if (!(ObjectUtil.equal(entity.getStatus(), OrderStatusEnum.NEWS.getValue())
                    || ObjectUtil.equal(entity.getStatus(), OrderStatusEnum.NO_PASS.getValue()))) {
                throw new ServiceException("单据状态不正确，无法提交");
            }
            insertFlag = false;
        }

        // 重新计算一遍数据
        calcQuantity(entity, true);

        // 校验数量是否超过可退数量，并扣减可退数量
        submitValidRefundQuantity(entity);

        // 添加必要信息
        entity.setGroupCode(UserUtil.getBranchCode());
        entity.setCustomerName(customerCache.translate(entity.getCustomerCode()));
        entity.setShipmentCode(UserUtil.getShipmentCompanyCode());
        entity.setShipmentName(UserUtil.getShipmentCompanyName());
        entity.setStatus(OrderStatusEnum.PENDING.getValue());
        entity.setType(ReceiveTypeEnum.SALE_RETURN.getValue());
        // 判断flag，保存或update 主单
        if (insertFlag) {
            entity.setCode(OrderIdGeneratorUtil.generatorOmsOrderId(OrderIdGeneratorUtil.OrderTypeEnum.ST, entity.getShipmentCode(),UserUtil.getBranchCode()));
            save(entity);
        } else {
            entity.setModifiedBy(UserUtil.getCode());
            entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
            this.update(entity, new QueryWrapper<OmsSaleReturn>().lambda().eq(OmsSaleReturn::getCode, entity.getCode()));
        }

        // 删除数据库中的子单
        iSaleReturnItemService.remove(new QueryWrapper<OmsSaleReturnItem>().lambda().eq(OmsSaleReturnItem::getSaleReturnCode, entity.getCode()));
        // 子单添加信息
        entity.getSaleReturnItemList().forEach(r -> {
            r.setCode(IdUtil.simpleUUID());
            r.setSaleReturnCode(entity.getCode());
            r.setCreatedBy(entity.getCreatedBy());
            r.setCreatedName(entity.getCreatedName());
            r.setModifiedBy(entity.getModifiedBy());
            r.setModifiedName(entity.getModifiedName());
        });
        // 保存子单
        iSaleReturnItemService.saveBatch(entity.getSaleReturnItemList());
    }

    /**
     * @param entity :
     * @description 审核
     * @author xuyang
     * @date 2020/12/14 14:19
     **/
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void audit(OmsSaleReturn entity) {
        if (!StrUtil.equalsAny(entity.getStatus(), OrderStatusEnum.NO_PASS.getValue(), OrderStatusEnum.PASS.getValue())){
            throw new ServiceException("审核状态不正确");
        }
        // 获取数据库数据
        OmsSaleReturn dbEntity = this.getOne(new QueryWrapper<OmsSaleReturn>().lambda().eq(OmsSaleReturn::getCode, entity.getCode()));
        if (ObjectUtil.isNull(dbEntity)) {
            throw new ServiceException("单据不存在");
        }
        // 校验数据库数据状态
        if (ObjectUtil.notEqual(dbEntity.getStatus(), OrderStatusEnum.PENDING.getValue())) {
            throw new ServiceException("单据不是待审核状态，无法审核。");
        }
        // 判断审核状态
        if (OrderStatusEnum.NO_PASS.getValue().equals(entity.getStatus())) {
            // 审核未通过，判断审核意见是否填写
            if (StrUtil.isBlank(entity.getVerifyOpinion())) {
                throw new ServiceException("审核意见不能为空。");
            }
            // 释放被占的销售单退货数量
            releaseRefundQuantity(entity.getCode());
        }

        // 保存审核单（用数据库数据，修改状态、意见、增加审核人、时间。。。。）
        dbEntity.setStatus(entity.getStatus());
        entity.setModifiedBy(UserUtil.getCode());
        entity.setModifiedName(partyCache.translate(UserUtil.getCode()));
        dbEntity.setVerifyOpinion(entity.getVerifyOpinion());
        dbEntity.setVerifyBy(UserUtil.getCode());
        dbEntity.setVerifyName(partyCache.translate(UserUtil.getCode()));
        this.updateById(dbEntity);

        //处理组合商品
        composeToDetail(dbEntity);
        // 审核通过
        if (OrderStatusEnum.PASS.getValue().equals(entity.getStatus())) {
            // 审核通过后续，生成出库单或调用wms生成采购单
            afterAuditPass(dbEntity);
        }
    }

    /**
     * 处理组合商品
     * @param dbEntity
     */
    private void composeToDetail(OmsSaleReturn dbEntity) {
        //所有商品
        List<OmsSaleReturnItem> saleItems = iSaleReturnItemService.list(new QueryWrapper<OmsSaleReturnItem>().lambda().eq(OmsSaleReturnItem::getSaleReturnCode, dbEntity.getCode()));
        //销售商品中是组合类型的
        List<OmsSaleReturnItem> composeList = saleItems.stream().filter(v -> OmsGoodTypeEnum.GOOD_TYPE_COMPOSE.getCode().equals(v.getRecordType())).collect(Collectors.toList());
        //删除组合商品
        saleItems.removeAll(composeList);
        //处理组合商品
        BigDecimal planQuantity = dbEntity.getPlanQuantity();
        BigDecimal planBasicQuantity = dbEntity.getPlanBasicQuantity();
        for (OmsSaleReturnItem saleItem : composeList) {
            BigDecimal totalMoney = saleItem.getTotalMoney();
            BigDecimal amountMoney = saleItem.getAmountMoney();
            List<OmsGoodsRelationItem> goodsList = iOmsGoodsRelationItemService.list(new QueryWrapper<OmsGoodsRelationItem>().lambda().eq(OmsGoodsRelationItem::getGoodsRelationCode, saleItem.getGoodsCode()));
            totalMoney = totalMoney.divide(BigDecimal.valueOf(goodsList.size()), 6, BigDecimal.ROUND_HALF_UP);
            amountMoney = amountMoney.divide(BigDecimal.valueOf(goodsList.size()), 6, BigDecimal.ROUND_HALF_UP);
            planQuantity = planQuantity.subtract(saleItem.getPlanQuantity());
            planBasicQuantity = planBasicQuantity.subtract(saleItem.getPlanQuantity());
            for (OmsGoodsRelationItem item : goodsList) {
                OmsSaleReturnItem newSaleItem = new OmsSaleReturnItem();
                BeanUtil.copyProperties(item, newSaleItem);
                newSaleItem.setSaleReturnCode(saleItem.getSaleReturnCode());
                newSaleItem.setReturnUnit(item.getBasicUnit());
                newSaleItem.setReturnUnitName(item.getBasicUnitName());
                BigDecimal itemPlanBasicQuantity = saleItem.getPlanBasicQuantity().multiply(item.getPlanBasicQuantity());
                newSaleItem.setPlanBasicQuantity(itemPlanBasicQuantity);
                BigDecimal itemPlanQuantity = saleItem.getPlanQuantity().multiply(item.getPlanQuantity());
                newSaleItem.setPlanQuantity(itemPlanQuantity);
                newSaleItem.setUnitPrice(item.getDeliveryPrice());
                newSaleItem.setTaxUnitPrice(item.getDeliveryPrice());
                newSaleItem.setAmountMoney(amountMoney);
                newSaleItem.setTaxMoney(totalMoney);
                newSaleItem.setTotalMoney(totalMoney);
                newSaleItem.setRemarks(saleItem.getRemarks());
                newSaleItem.setComposeGoodCode(saleItem.getCode());
                saleItems.add(newSaleItem);
                planQuantity = planQuantity.add(newSaleItem.getPlanQuantity());
                planBasicQuantity = planBasicQuantity.add(newSaleItem.getPlanBasicQuantity());
            }
        }
        dbEntity.setSaleReturnItemList(saleItems);
        dbEntity.setPlanQuantity(planQuantity);
        dbEntity.setPlanBasicQuantity(planBasicQuantity);
    }


    /**
     * 本地保存时校验可退数量
     *
     * @param items
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    public void localSaveValidRefundQuantity(List<OmsSaleReturnItem> items) {
        // 遍历， 根据item中关联的销售单item，获取数量，计算item出库数量 - 已退数量 - 拟退数量
        items.stream().forEach(e -> {
            if (ObjectUtil.isNull(e.getPlanBasicQuantity()) || e.getPlanBasicQuantity().compareTo(BigDecimal.ZERO) <= 0) {
                throw new ServiceException("退货数量必须大于0");
            }

            SaleItem saleItem = iSaleItemService.getOne(new QueryWrapper<SaleItem>().lambda().eq(SaleItem::getCode, e.getSaleItemCode()));
            BigDecimal diffQuantity = saleItem.getActualBasicQuantity().subtract(saleItem.getRefundBasicQuantity()).subtract(e.getPlanBasicQuantity());
            if (diffQuantity.compareTo(BigDecimal.ZERO) < 0) {
                throw new ServiceException("商品“" + e.getGoodsName() + "”退货数量超过了可退数量，无法退货");
            }
        });
    }

    /**
     * 提交时校验可退数量，并扣减销售单明细的已退数量
     *
     * @param saleReturn
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    public void submitValidRefundQuantity(OmsSaleReturn saleReturn) {
        // 基本单位总退货数量, 用于更新销售单主单的退货数量
        BigDecimal totalRefundBasicQuantity = BigDecimal.ZERO;
        BigDecimal totalRefundQuantity = BigDecimal.ZERO;
        // 遍历， 根据item中关联的销售单item，获取数量，计算item出库数量 - 已退数量 - 拟退数量
        for (OmsSaleReturnItem e : saleReturn.getSaleReturnItemList()) {
            if (ObjectUtil.isNull(e.getPlanBasicQuantity()) || e.getPlanBasicQuantity().compareTo(BigDecimal.ZERO) <= 0) {
                throw new ServiceException("退货数量必须大于0");
            }
            // 更新销售单退货数量，判断 实际销售数量 >= 原退货数量 + 本次退货数量，否则无法退货
            boolean updateFlag = iSaleItemService.update(new UpdateWrapper<SaleItem>().lambda().eq(SaleItem::getCode, e.getSaleItemCode())
                    .setSql(" refund_quantity = refund_quantity + " + e.getPlanQuantity())
                    .setSql(" refund_basic_quantity = refund_basic_quantity + " + e.getPlanBasicQuantity())
                    .apply(" actual_basic_quantity >= refund_basic_quantity + " + e.getPlanBasicQuantity()));
            if (!updateFlag) {
                throw new ServiceException("商品“" + e.getGoodsName() + "”退货数量超过了可退数量，无法退货");
            }

            totalRefundBasicQuantity = totalRefundBasicQuantity.add(e.getPlanBasicQuantity());
            totalRefundQuantity = totalRefundQuantity.add(e.getPlanQuantity());
        }

        // 增加销售单退货数量
        iSaleService.update(new UpdateWrapper<Sale>().lambda().eq(Sale::getCode, saleReturn.getSourceCode())
                .setSql(" refund_basic_quantity = refund_basic_quantity + " + totalRefundBasicQuantity)
                .setSql(" refund_quantity = refund_quantity + " + totalRefundQuantity));
    }

    /**
     * @param entity:
     * @param usePlanQuantityFlag: true 使用计划数量计算； false：使用实际数量计算
     * @description 根据退货单数量，计算各种金额数据
     * @author xuyang
     * @date 2020/12/14 14:05
     **/
    @Override
    public void calcQuantity(OmsSaleReturn entity, boolean usePlanQuantityFlag) {
        // 计算订单总数（销售单位、基本单位）
        BigDecimal planQuantity = BigDecimal.ZERO, planBasicQuantity = BigDecimal.ZERO;
        // 计算实际数量总数
        BigDecimal actualQuantity = BigDecimal.ZERO, actualBasicQuantity = BigDecimal.ZERO;
        // 计划数量/实际数量，根据usePlanQuantityFlag判断使用哪个
        BigDecimal basicCalcQuantity;

        Goods goods;
        Integer unitPrecision;
        for (OmsSaleReturnItem e : entity.getSaleReturnItemList()) {
            // 根据转换率、单价、税率等，需要计算出基本单位的数量、总价等信息
            goods = goodsCache.getObj(e.getGoodsCode());
            if (ObjectUtil.isNull(goods)) {
                throw new ServiceException("商品【" + e.getGoodsName() + "】信息不存在");
            }
            // 处理商品数量精度
            unitPrecision = goods.getUnitPrecision().intValue();

            if (usePlanQuantityFlag) {
                basicCalcQuantity = e.getPlanQuantity();
            } else {
                basicCalcQuantity = e.getActualQuantity();
            }
            e.setPlanBasicQuantity(e.getPlanQuantity().multiply(e.getUnitConvertQuantity()).setScale(unitPrecision, BigDecimal.ROUND_HALF_UP));
            if (ObjectUtil.isNotNull(e.getActualQuantity())) {
                e.setActualBasicQuantity(e.getActualQuantity().multiply(e.getUnitConvertQuantity()).setScale(unitPrecision, BigDecimal.ROUND_HALF_UP));
            }

            // 含税单价 = 单价*税率/100 + 单价
            e.setTaxUnitPrice(e.getUnitPrice().multiply(e.getTaxRate()).divide(DECIMAL100).add(e.getUnitPrice()).setScale(6, BigDecimal.ROUND_HALF_UP));
            // 金额 = 单价*销售数量
            e.setAmountMoney(e.getUnitPrice().multiply(basicCalcQuantity).setScale(6, BigDecimal.ROUND_HALF_UP));

            // 税额 = 单价*销售数量*税率/100  保留6位小数
            e.setTaxMoney(e.getUnitPrice().multiply(basicCalcQuantity).multiply(e.getTaxRate()).divide(DECIMAL100).setScale(6, BigDecimal.ROUND_HALF_UP));
            // 价税合计 = 金额 + 税额 ; 重新再计算一遍，避免前面保留小数位数造成精度丢失
            e.setTotalMoney(e.getUnitPrice().multiply(basicCalcQuantity).add(
                    e.getUnitPrice().multiply(basicCalcQuantity).multiply(e.getTaxRate()).divide(DECIMAL100)
            ).setScale(6, BigDecimal.ROUND_HALF_UP));

            // 计算计划总量
            planQuantity = planQuantity.add(ObjectUtil.defaultIfNull(e.getPlanQuantity(), BigDecimal.ZERO));
            planBasicQuantity = planBasicQuantity.add(ObjectUtil.defaultIfNull(e.getPlanBasicQuantity(), BigDecimal.ZERO));

            // 计算实际总量
            actualQuantity = actualQuantity.add(ObjectUtil.defaultIfNull(e.getActualQuantity(), BigDecimal.ZERO));
            actualBasicQuantity = actualBasicQuantity.add(ObjectUtil.defaultIfNull(e.getActualBasicQuantity(), BigDecimal.ZERO));
        }
        entity.setPlanQuantity(planQuantity);
        entity.setPlanBasicQuantity(planBasicQuantity);
        entity.setActualQuantity(actualQuantity);
        entity.setActualBasicQuantity(actualBasicQuantity);

    }

    /**
     * @param code:
     * @description 释放销售单退货数量
     * @author xuyang
     * @date 2020/12/14 14:35
     **/
    @Transactional(rollbackFor = {Exception.class})
    public void releaseRefundQuantity(String code) {
        OmsSaleReturn saleReturn = getOne(new QueryWrapper<OmsSaleReturn>().lambda().eq(OmsSaleReturn::getCode, code));
        if (saleReturn == null) {
            throw new ServiceException("销售退货单【" + code + "】不存在");
        }
        List<OmsSaleReturnItem> items = iSaleReturnItemService.list(new QueryWrapper<OmsSaleReturnItem>().lambda().eq(OmsSaleReturnItem::getSaleReturnCode, code));
        BigDecimal adjustQuantity = BigDecimal.ZERO;
        BigDecimal adjustBasicQuantity = BigDecimal.ZERO;
        for (OmsSaleReturnItem e: items) {
            iSaleItemService.update(new UpdateWrapper<SaleItem>().lambda().eq(SaleItem::getCode, e.getSaleItemCode())
                    .setSql(" refund_quantity = refund_quantity - " + e.getPlanQuantity())
                    .setSql(" refund_basic_quantity = refund_basic_quantity - " + e.getPlanBasicQuantity())
                    .apply(" refund_basic_quantity >= " + e.getPlanBasicQuantity()));
            adjustQuantity = adjustQuantity.add(e.getPlanQuantity());
            adjustBasicQuantity = adjustBasicQuantity.add(e.getPlanBasicQuantity());
        }
        // 释放主单占用的退货数额
        iSaleService.update(new UpdateWrapper<Sale>().lambda().eq(Sale::getCode, saleReturn.getSourceCode())
            .setSql(" refund_quantity = refund_quantity - " + adjustQuantity)
            .setSql(" refund_basic_quantity = refund_basic_quantity - " + adjustBasicQuantity));
    }


    /**
     * 审核通过后生成oms出库单（负数的），或调用wms生成收货单
     *
     * @param entity
     */
    @Transactional(rollbackFor = {Exception.class})
    public void afterAuditPass(OmsSaleReturn entity) {
        // 获取仓库
        Map<String, Object> warehouseMap = warehouseCache.get(entity.getWarehouseCode());
        Integer locationManagement = MapUtil.get(warehouseMap, "locationManagement", Integer.class);
        if (ObjectUtil.isNull(locationManagement)) {
            throw new ServiceException("仓库没有维护“启用库位管理”");
        }
        // 如果没有实体库位-》直接生成oms出库单
        if (locationManagement.equals(NUM_ZERO)) {
            // 直接生成oms出库单, 回填销售退单的实际出库数量
            OmsSaleReturnVO vo = getByCode(entity.getCode());
            iOmsOutboundService.saveBySaleReturn(vo, NUM_ZERO,null);
        } else {
            //TODO 如果有实体库位-》调用wms收货单，生成收货单
            // 生成wms收货单
            iReceiveService.createByOmsSaleReturn(entity);
        }
    }

    /**
     * @param code:
     * @description 获取明细vo
     * @author xuyang
     * @date 2020/12/14 15:02
     **/
    @Override
    public OmsSaleReturnVO getByCode(String code) {
        OmsSaleReturn entity = getOne(new QueryWrapper<OmsSaleReturn>().lambda().eq(OmsSaleReturn::getCode, code));
        if (ObjectUtil.isNotNull(entity)) {
            OmsSaleReturnVO vo = new OmsSaleReturnVO();
            BeanUtil.copyProperties(entity, vo, false);
            // 需要关联收货明细，查询可退数量字段
            OmsSaleReturnItemDTO itemDTO = new OmsSaleReturnItemDTO();
            itemDTO.setSaleReturnCode(vo.getCode());
            List<OmsSaleReturnItemVO> itemVOs = iSaleReturnItemService.queryListWithRefundInfo(itemDTO);
            // 翻译
            vo.setWarehouseName(warehouseCache.translate(vo.getWarehouseCode()));
            vo.setTypeText(ReceiveTypeEnum.translate(vo.getType()));

            vo.setSaleReturnItemList(itemVOs);
            return vo;
        }
        return null;
    }

    /**
     * @param saleReturnCode :
     * @description 根据销售退货单单号，查询出库单更新销售退货数量
     * @author xuyang
     * @date 2020/12/14 17:13
     **/
    @Override
    public void updateOutQuantityByItems(String saleReturnCode) {
        this.baseMapper.updateOutQuantityByItems(saleReturnCode);
    }

    /**
     * @param saleReturnCode :
     * @description wms根据销售退货单生成oms出库单
     * @author xuyang
     * @date 2020/12/15 13:10
     **/
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void wmsSaveOmsOutboundBySaleReturn(String saleReturnCode, Putaway putaway) {
        OmsSaleReturnVO vo = getByCode(saleReturnCode);
        iOmsOutboundService.saveBySaleReturn(vo, NumConst.NUM_ONE,putaway);
    }

    /**
     * @param sourceCode :
     * @description 根据计划数量与实际数量的差，调整销售单的退货数量
     * @author xuyang
     * @date 2020/12/15 16:03
     **/
    @Override
    public void adjustSaleRefundQuantity(String sourceCode) {
        List<OmsSaleReturnItem> items = iSaleReturnItemService.list(new QueryWrapper<OmsSaleReturnItem>().lambda().eq(OmsSaleReturnItem::getSaleReturnCode, sourceCode));
        items.stream().forEach(e->{
            if (ObjectUtil.isNotNull(e.getActualBasicQuantity())) {
                BigDecimal diffQuantity = e.getActualBasicQuantity().subtract(e.getPlanBasicQuantity());
                BigDecimal diffUnitQuantity = e.getActualQuantity().subtract(e.getPlanQuantity());
                // 差异数量为负数时，更新， 正常情况下， 实际数量-计划数量 应该 <= 0, 0时不用更新
                if (diffQuantity.compareTo(BigDecimal.ZERO) < 0) {
                    iSaleItemService.update(new UpdateWrapper<SaleItem>().lambda().eq(SaleItem::getCode, e.getSaleItemCode())
                        .setSql(" refund_basic_quantity = refund_basic_quantity + " + diffQuantity)
                        .setSql(" refund_quantity = refund_quantity + " + diffUnitQuantity));
                }
            }
        });
    }

    /**
     * @description
     * 由于前端明细数据是从销售单明细中获取的，所以部分相同字段可能被销售明细覆盖内容了
     * @author xuyang
     * @date 2020/12/24 17:17
     * @param entity:
     **/
    public void clearOtherInfo(OmsSaleReturn entity) {

    }

}
